package sesion;

import Entities.Cliente;
import Entities.Especial;
import Entities.Externo;
import Entities.Interno;
import Entities.MenuEjecutivo;
import Entities.Mesa;
import Entities.Pedido;
import Entities.Producto;
import Entities.Reserva;
import Entities.Usuario;
import ejb.Condicional;
import ejb.UsuarioFacadeLocal;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;

/**
 * Clase de sesion que maneja permisos, sesion del usuario.
 */
@ManagedBean
@SessionScoped
public class Sesion implements Serializable {

    @EJB
    private UsuarioFacadeLocal usuarioFacade;
    private String nombreUsuario;
    private String contrasenia;
    private Usuario usuario;
    private boolean activa = false;

    public Sesion() {
        this.usuario = new Cliente();
        this.nombreUsuario = "";
        this.contrasenia = "";
    }

    /**
     * Obtengo los permisos de la clase.
     *
     * @param clase
     * @return
     */
    public PermisoPagina consultarPermisos(Class clase) {
        PermisoPagina pp = new PermisoPagina();
        try {
            switch (usuario.getRol()) {
                case 1: //Caja
                    if (clase == Pedido.class
                            || clase == Interno.class
                            || clase == Externo.class) {
                        pp.setFacturar(true);
                        pp.setModificacion(true);
                    }
                    break;
                case 2: //Chofer
                    break;
                case 3: //Cliente
                    if (clase == Producto.class) {
                        pp.setVer(true);
                    }
                    if (clase == Externo.class) {
                        pp.setAlta(true);
                        pp.setBaja(true);
                    }
                    if (clase == Reserva.class) {
                        pp.setAlta(true);
                    }
                    if (clase == Especial.class) {
                        pp.setVer(true);
                    }
                    if (clase == MenuEjecutivo.class) {
                        pp.setVer(true);
                    }
                    break;
                case 4: //Maitre
                    if (clase == Producto.class
                            || clase == Mesa.class
                            || clase == Reserva.class
                            || clase == Pedido.class
                            || clase == Externo.class
                            || clase == MenuEjecutivo.class
                            || clase == Especial.class) {
                        pp.setAlta(true);
                        pp.setModificacion(true);
                        pp.setBaja(true);
                    }
                    break;
                case 5: //Mozo
                    if (clase == Reserva.class
                            || clase == Pedido.class
                            || clase == Interno.class) {
                        pp.setAlta(true);
                        pp.setModificacion(true);
                        pp.setBaja(true);
                    }
                    break;
                case 6: //SuperUsuario
                    pp.setAlta(true);
                    pp.setModificacion(true);
                    pp.setBaja(true);
                    pp.setFacturar(true);
                    break;
            }
            if (usuario.getRol() != 3) {
                pp.setVer(true);
            }
        } catch (Exception e) {
        }
        /*
         * maitre = productos, mesas, reservas y pedidos
         * su = todo
         * mozo = pedidos, reserva
         * 
         */
        return pp;
    }

    public boolean isMostrarTituloTabla() {
        return true;
    }

    /**
     * Compruebo que este logueada la persona o que tenga permisos. de forma de
     * reedireccionar segun sea necesario.
     */
    public void comprobar() {

        try {
            FacesContext context = FacesContext.getCurrentInstance();
            HttpServletRequest origRequest = (HttpServletRequest) context.getExternalContext().getRequest();
            String tmp = origRequest.getRequestURL().toString();
            tmp = tmp.substring(0, tmp.indexOf(origRequest.getContextPath())) + origRequest.getContextPath();
            context.getExternalContext().redirect(tmp + "/login/login.xhtml");
        } catch (Exception ex) {
            ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();;
            try {
                context.redirect(context.getRequestContextPath());
            } catch (IOException ex1) {
                Logger.getLogger(Sesion.class.getName()).log(Level.SEVERE, null, ex1);
            }
        }

    }

    public void comprobarCliente() {
        try {
            if (this.getUsuario().getRol().equals(3)) {
                FacesContext context = FacesContext.getCurrentInstance();
                HttpServletRequest origRequest = (HttpServletRequest) context.getExternalContext().getRequest();
                String tmp = origRequest.getRequestURL().toString();
                tmp = tmp.substring(0, tmp.indexOf(origRequest.getContextPath())) + origRequest.getContextPath();
                context.getExternalContext().redirect(tmp + "/paginasUsuario/index.xhtml");
            }
        } catch (IOException ex) {
        }

    }

    public boolean isActiva() {
        return this.activa;
    }

    public String getNombreUsuario() {
        return nombreUsuario;
    }

    public void setNombreUsuario(String nombreUsuario) {
        this.nombreUsuario = nombreUsuario;
    }

    public String getContrasenia() {
        return contrasenia;
    }

    public void setContrasenia(String contrasenia) {
        this.contrasenia = contrasenia;
    }

    public void resetearValores() {
        this.nombreUsuario = null;
        this.contrasenia = null;
    }

    public Usuario getUsuario() {
        return usuario;
    }

    public void setUsuario(Usuario usuario) {
        this.usuario = usuario;
    }

    /**
     * Manejo el login del usuario
     */
    public void login() {
        try {
            Condicional cond1 = new Condicional("nombreUsuario", this.nombreUsuario, "=");
            Condicional cond2 = new Condicional("contrasenia", codificarPassword(this.contrasenia), "=");
            Condicional cond3 = new Condicional("activo", true, "=");
            List<Condicional> parametros = new ArrayList<>();
            parametros.add(cond1);
            parametros.add(cond2);
            parametros.add(cond3);
            List<Usuario> lista = usuarioFacade.buscarConParametros(parametros, null, new int[]{0, 1});
            if (lista != null && lista.size() > 0) {
                this.usuario = lista.get(0);
                this.activa = true;
                try {
                    ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
                    if (lista.get(0).getRol() != 3) {
                        context.redirect(context.getRequestContextPath() + "/paginas/index.xhtml");
                    } else {
                        context.redirect(context.getRequestContextPath());
                    }
                } catch (IOException ex) {
                }
            } else {
                this.contrasenia = null;
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Usuario y/o contraseña incorrecta", null));
            }
        } catch (Exception e) {
        }
    }

    /**
     * Manejo el logout del usuario
     */
    public void logout() {
        ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
        HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
                .getExternalContext().getSession(false);
        this.activa = false;
        this.usuario = new Cliente();
        this.nombreUsuario = "";
        this.contrasenia = "";
        session.invalidate();
        try {
            context.redirect(context.getRequestContextPath());
        } catch (IOException ex) {
            Logger.getLogger(Sesion.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    private String dirImagen;

    public String getDirImagen() {
        return dirImagen;
    }

    public void setDirImagen(String dirImagen) {
        this.dirImagen = dirImagen;
    }

    public StreamedContent devolverImagen() {
        try {
            //create an InputStream from the uploaded file
            InputStream inputStr = new FileInputStream(new File(this.dirImagen));
            return new DefaultStreamedContent(inputStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new DefaultStreamedContent();
    }

    public StreamedContent devolverImagenDesdeRuta(String ruta) {
        if (ruta != null && !ruta.isEmpty()) {
            try {
                //create an InputStream from the uploaded file
                InputStream inputStr = new FileInputStream(new File(ruta));
                return new DefaultStreamedContent(inputStr);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        DefaultStreamedContent d = null;
        try {
            d = new DefaultStreamedContent();
        } catch (Exception e) {
        }
        return d;
    }

    private String toHexadecimal(byte[] digest) {
        String hash = "";
        for (byte aux : digest) {
            int b = aux & 0xff;
            if (Integer.toHexString(b).length() == 1) {
                hash += "0";
            }
            hash += Integer.toHexString(b);
        }
        return hash;
    }

    /**
     * Manejo el password para codificarlo
     *
     * @param cadena
     * @return
     */
    private String codificarPassword(String cadena) {
        byte[] digest = null;
        byte[] buffer = cadena.getBytes();
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.reset();
            messageDigest.update(buffer);
            digest = messageDigest.digest();
        } catch (NoSuchAlgorithmException ex) {
        }
        return toHexadecimal(digest);
    }
}
